Microsoft veröffentlicht demnächst eine Admin-Shell für Windows, die diesen Namen auch verdient. Beim Pipelining verhält sich die Powershell unter Umständen sogar robuster als die Unix-Pendants, weil sie typisierte Objekte durchreicht.
Windows ist der Inbegriff für (bunte) grafische Oberflächen, die ohne Maus faktisch unbedienbar sind. Des Einsteigers Freud ist des Admin Leid, wenn er sich bei wiederkehrenden Alltagsaufgaben die Finger wund klickt. Denn die mit Windows gelieferte Kommandozeilen-Schnittstelle ist seit DOS-Zeiten kaum verändert und funktional ein Torso.
Erkannt hat Microsoft dieses Problem bereits Ende der 90er Jahre. Damals entstand der Windows Script Host (WSH), anfangs auch Windows Scripting Host genannt. Mit dem WSH übertrug Microsoft das zu dieser Zeit aufkommende Browser-Scripting mit Javascript und VBscript auf das Betriebssystem. Technisch basiert der WSH auf dem Component Object Model (COM), einem Softwarekomponenten-Modell, das viele Windows-Anwendungen und auch Teile des Betriebssystems verwenden.
Positiv am WSH ist, dass der Administrator sowohl Windows-Systemdienste als auch Anwendungen wie Word, Excel und Powerpoint mit den gleichen Instrumenten steuern kann. So sind Skripte möglich, die den Zustand von Windows in Excel oder Word dokumentieren. Negativ ist, dass der Administrator zum Erreichen dieser Ziele ein breites Wissen über objektorientiertes Programmieren und Softwarekomponenten braucht, denn COM richtet sich an Programmierer, nicht an Administratoren.
Von Unix-Admins gelernt
Im Zuge der Entwicklung von Windows Server 2003 gab Microsoft eine Studie in Auftrag, bei der Unix-Administratoren gefragt wurden, welche Werkzeuge sie benutzen. Als kurzfristige Folge – Linuxer wundert\’s kaum – hat Microsoft die Anzahl der Kommandozeilen-Werkzeuge im Server kräftig erhöht. Langfristig entwickelte der Konzern über die Zwischenstufen Monad sowie Microsoft Shell (MSH) eine neue Kommandozeilen-Schnittstelle, die Powershell.
Derzeit gibt es sie als Release Candidate 2, was bei Microsoft bedeutet, dass fast alle angepeilten Funktionen enthalten sind. Bis zur endgültigen Version, geplant für das Jahresende 2006, sind noch kleinere Polituren zu erwarten. Die Powershell ist nicht Teil eines Betriebssystems, auch nicht des kommenden Windows Vista, sondern ein kostenfreies Zusatzprodukt. Die aktuelle Vorabversion findet gibt\’s unter [1].
Auf den ersten Blick (Abbildungen 1 und 3) präsentiert sich das Produkt wie ein klassisches DOS-Kommandozeilenfenster. Unter der Haube steckt aber mehr, beispielsweise bessere Eingabehilfen (Tab Completion). Einen echten Editor liefert Microsoft jedoch nicht. Hier sind bereits Drittanbieter ([2], [3]) aktiv.
Die Befehle in der Powershell heißen Commandlets und sind nach einer Namenskonvention aufgebaut: Sie bestehen immer aus einem Verb und einem Substantiv, zum Beispiel »get-service«, »start-service«, »get-process« oder »select-object«. Eine Parameterliste ist optional. Sind die Parameter unbenannt, dann entscheidet die Reihenfolge, sind sie benannt, muss der Windows-Benutzer dem Parameternamen einen Strich voranstellen. Bei den Parameterwerten sind Platzhalter wie »*« und »?« sowie »[Menge]« erlaubt. Die Groß- und Kleinschreibung ist irrelevant.
Commandlets konkret
Mit dem folgenden Befehl erhält der Administrator eine Liste der laufenden Prozesse, die mit »I« oder »i« anfangen:
get-process -name i*
Ohne die Benennung des Parameters (»get-process i*«) gibt es das gleiche Ergebnis, wie Abbildung 1 nahe legt. Für viele Commandlets sind Aliase definiert, um den Befehl kürzer ausdrücken zu können: »gps i*« oder »ps i*«. »get-alias« listet Aliase, »set-alias« legt einen eigenen an (siehe Tabelle 1).
|
Tabelle 1: |
|||
|---|---|---|---|
|
Funktion |
Bash |
Powershell |
Powershell-Alias |
|
Kommentar |
# |
# |
– |
|
Hilfe |
man, info |
get-help |
help |
|
Ausgabe |
echo |
Einfacher Ausdruck oder zahlreiche Commandlets, die mit |
– |
|
Variablen |
$ |
$ |
– |
|
Pipe |
| |
| |
– |
|
Hintergrundverarbeitung |
& |
Möglich nur über komplizierten Zugriff auf Dotnet-Klassen |
– |
|
Platzhalter und reguläre Ausdrücke |
*, ?, [ ], ~ |
*, ?, [ ], -match |
– |
|
Ersetzen |
gawk |
-replace |
– |
|
Einbinden von Skripten |
».« |
».« |
– |
|
Bedingung |
if [ Bedingung ] ? fi |
if ( Bedingung ) { ? } |
– |
|
Schleife mit Bedingung |
while [ Bedingung ] do ? done |
while (Bedingung) { ? } |
– |
|
Schleife über Menge |
for x [ in Liste ] do ? done |
foreach-object x { ? } (Bezug ist der Pipeline-Inhalt) |
– |
|
Umlenkung |
>, < |
>, < und diverse »import…« und »export…«- Commandlets |
– |
|
Verzeichnis auflisten |
ls, dir |
get-childitem |
ls, dir |
|
Verzeichnis anlegen |
mkdir |
new-item |
md, mkdir |
|
Verzeichniswechsel |
cd |
set-location |
cd |
|
Datei-Inhalte anzeigen |
cat |
get-content |
cat, type, gc |
|
Datei löschen |
rm |
remove-item |
del, ri, rm, erase, rd |
|
Prozessliste |
ps |
get-process |
ps, gps |
|
Filtern |
grep, sed, head, tail, find, cut |
where-object, select-object |
where, select |
|
Zählen/Berechnen |
wc, du, etc. |
measure-object |
– |
|
Sortieren |
sort |
sort-object |
sort |
|
Aktuelles Datum |
date |
get-date |
– |
|
Befehlsgeschichte |
history |
get-history |
history, h |
|
Alias anlegen |
alias |
set-alias |
alias |
Ein weiteres Beispiel für ein Commandlet: Mit »stop-process -name iexplore*« entledigt sich der Anwender aller laufenden Instanzen des Internet Explorers. Beim Einstieg in die Powershell sind wichtig: »get-command« liefert eine Liste aller Commandlets, »get-help« oder »help« leistet Hilfe zu einem Commandlet, so beispielsweise »get-help get-service«. »get-help get« zeigt alle Commandlets, die mit »get« anfangen.
Pipelining in Unix tendenziell etwas anfällig
Bis hierhin beeindruckt wenig, alles war in Windows schon früher in einer Zeile möglich. Anders beim aus Unix-Shells bekannten Pipelining, also der Übergabe von Daten von einem Befehl an einen zweiten. Bash&Co. reichen dabei Zeichenketten oder binäre Daten weiter; die Standardausgabe eines Befehls wird zur Standardeingabe des nächsten. Sind dabei Informationen aufzubereiten, schalten Linuxer Tools wie »grep«, »awk« und andere zwischen.
Das Damoklesschwert, das über dem Screen Scraping schwebt: Wenn eines der Tools in der Kette wegen eines Updates oder geänderter Rahmenbedingungen (etwa einer gesetzten Shellvariablen) seine Ausgabe unpassend ändert, geht die Weitergabe schief.
Microsoft geht daher beim Pipelining einen anderen Weg: Die Powershell tauscht nicht Texte oder Rohdaten, sondern typisierte Dotnet-Objekte aus. Das Dotnet-Framework [4] ist ein Softwarekomponenten-Modell, das im Jahr 2002 eingeführte Nachfolgeprodukt zum Component Object Model (COM). Die Powershell fußt auf Dotnet, allerdings ohne im bisherigen Maße Programmierkenntnisse vorauszusetzen.
Eine typische Powershell-Pipeline sieht folgendermaßen aus:
get-process | where-object { $_.workingset64 -gt 10M } | sort-object workingset64 -desc
Der Befehl holt eine Liste aller laufenden Prozesse, filtert jene heraus, die mehr als 10 MByte Speicher beanspruchen, und sortiert sie absteigend nach dem Speicherbedarf. Die Befehlszeile funktioniert unabhängig davon, welche Daten »get-process« liefert, solange es in den gelieferten Objekten eine Eigenschaft mit Namen »workingset64« gibt.
Durchreiche für Objekte
Abbildung 2 veranschaulicht das Verfahren: Das erste Commandlet legt eine Menge von Dotnet-Objekten in die Pipeline. Im Fall von »get-process« sind dies Instanzen der Klasse »System.Diagnostics.Process« (die Dotnet-Klassen haben mehrgliederige Namen). Der Powershell Pipeline Processor übergibt diese Objekte sukzessive an das zweite Commandlet »where-object«. Dies filtert Objekte und übergibt den Rest zur Sortierung an »sort-object«. Letzteres wirkt wie alle Commandlets auf jede Art von Objekten.

Abbildung 2: Beim Pipelining in der Powershell laufen typisierte Objekte von Commandlet zu Commandlet.

Abbildung 3: Die Powershell definiert den Begriff “Laufwerk” sehr weit, indem sie Umgebungsvariablen, Aliase und die Registrierungsdatenbank ebenfalls einbezieht.
Die Pipeline kann auch einzelne elementare Daten befördern. Einige Commandlets unterstützen das Auslesen der Parameter aus der Pipeline. Der folgende Pipeline-Befehl führt zu einer Auflistung aller Windows-Systemdienste, die mit dem Buchstaben I beginnen.
"i*" | get-service
Eine Herausforderung bei der Arbeit besteht darin, zu wissen, welche Objekte sich in der Pipeline befinden und welche Fähigkeiten sie besitzen.
Mit Methode
Das Commandlet »get-member« ist hier hilfreich: Es zeigt den Dotnet-Klassennamen für die Objekte in der Pipeline sowie die Attribute und Methoden dieser Klasse. Auch die Methoden einer Klasse kann man aufrufen, um Aktionen auszuführen, die es zwar nicht als Commandlet, aber in den zugrunde liegenden Programmierschnittstellen gibt.
Der folgende Befehl wartet durch den Aufruf der Methode »WaitForExit()« in der Klasse »System.Diagnostics.Process« darauf, dass sich alle Instanzen von Microsoft Outlook beenden:
Get-Process "outlook" | foreach-object { $_.waitforexit() }
Wer über mehr Kenntnisse zum objektorientierten Entwickeln verfügt, darf die Programmierschnittstelle des Framework (in der Dotnet-Version 3.0 sind dies rund 10000 Klassen) auch direkt interaktiv ansprechen. Listing 1 zeigt am Beispiel des Anlegens eines Benutzers im Active Directory außerdem noch zwei weitere Dinge: Erstens lässt sich der Inhalt der Pipeline in Variablen ablegen, wobei ein Variablenname immer mit dem Dollarzeichen beginnt. Zweitens ist es möglich, Powershell-Befehle und Pipelines zu Skripten zusammenzufassen. Die Datei-Erweiterung ».ps1« steht für die Powershell-Version 1.0.
|
Listing 1: |
|---|
01 ###############################################
02 # Powershell-Skript: #
03 # Legt einen Benutzer im Active Directory an. #
04 # (C) Dr. Holger Schwichtenberg #
05 ###############################################
06 $pfad= "LDAP://ServerEssen06/OU=Geschaeftsfuerhung,DC=IT-Visions,DC=net"
07 $name = "Dr. Holger Schwichtenberg"
08 $NTname = "HolgerSchwichtenberg"
09 $ou = New-Object DirectoryServices.DirectoryEntry($pfad)
10 $user = $ou.get_Children().Add("CN=" + $name,'user')
11 $user.CommitChanges()
12 $user.SAMAccountName = $NTname
13 $user.l = "Washington"
14 $user.Description = "FBI Director"
15 $user.CommitChanges()
16 "Benutzer wurde angelegt: " + $user.get_Path()
|
Wer Listing 1 zu aufwändig findet, kann die Aufgabe in eine wieder verwendbare Funktion kapseln und als selbst entwickeltes Commandlet der Powershell hinzufügen. Nun verkürzt sich das Anlegen des Benutzers auf die Zeile:
Add-LDAPObject "LDAP://ServerEssen06/OU=Geschaeftsfuehrung,DC=IT-Visions,DC=net" -class "user" -rdn "cn=Dr. Holger Schwichtenberg"
Mehr Details über die Kapselung der LDAP-Funktion gibt\’s auf [5].
Management-Qualität
Ähnlich wie Dotnet-Objekte zieht die Powershell auch die Windows Management Instrumentation direkt heran. WMI ist die Redmonder Implementierung des Standards Web Based Enterprise Management (WBEM, [6]) zur Systemadministration. Auf einem modernen Windows-System bietet WMI rund 7000 Klassen mit Informationen über Hardware, Software und Konfiguration.
Der folgende Befehl liefert Daten über den freien Speicherplatz auf den Festplatten des Systems »E02«:
Get-WmiObject win32_logicaldisk -computer E02 | select name, freespace
Auch der Windows-Gerätemanager lässt sich auslesen:
Get-Wmiobject win32_videocontroller | select name, adapterram
Sprachwahl
Neben der Commandlet-Infrastruktur bietet die Powershell auch eine eigene Skriptsprache. Die Powershell Language (PSL) kennt neben Variablen die üblichen Programmkonstrukte wie Schleifen und Bedingungen. Microsoft nimmt keine Anleihe bei einer bestehende Skriptsprache, sondern hat sich für die Neuschöpfung nach eigenen Worten “inspirieren lassen” von den Unix-Shells, Perl, PHP, Python und C#.
Als Kontrollstrukturen kennt die MSCL folgende Konstrukte:
- if (Bedingung) {…} else {…}
- switch ($var) { Wert: {…} }
- while (Bedingung) { … }
- do { … } while (Bedingung)
- do { … } until (Bedingung)
- foreach ($var in $menge) {…}
- function name {…}
- return
- throw “Fehlertext”
- trap Fehlerklasse { … } else { … }
- throw Fehlerklasse
Das Kennzeichen für eine Variable ist das ». Die Variable ist entweder typlos (» = 5«) oder typisiert auf einen Powershell-Grundtyp oder eine beliebige Dotnet-Klasse:
$a = [int] 5 $a = [System.DataTime] "1.8.1972"
Für einige Datentypen, beispielsweise XML, hat die Powershell Sonderfunktionen integriert. Das folgende Beispiel greift über die Elementnamen in das XML-Dokument hinein:
$a = [xml] "<Shell><Name>PowerShell</Name><Hersteller>Microsoft</Hersteller></Shell>" $a.Shell.Hersteller
Operatoren werden durch Wörter (»-lt«, »-gt«) statt mit Sonderzeichen (<, >) ausgedrückt. Einzelne Operatoren heißen anders als üblich, beispielsweise »-match« für reguläre Ausdrücke. Ein wichtiger Unterschied ist, dass in Bedingungen und Schleifen die Ausdrücke nicht in eckigen, sondern in runden Klammern stehen. Blöcke begrenzt die Powershell mit geschweiften Klammern. Dennoch beweist Tabelle 1 die großen Ähnlichkeiten zur Bash.
Navigationsparadigma
Interessant ist auch das Administrationskonzept, das ein einheitliches Navigationsparadigma für alle Arten von Datenmengen aufweist. Beim Aufruf des Befehls »get-psdrive« (siehe Abbildung 3) zeigen sich nicht nur die erwarteten Laufwerke, sondern auch Umgebungsvariablen (»Env«), die Registrierungsdatenbank (»HKCU«, »HKLM«) und die Aliase.
Die Powershell fasst auch diese Daten als Laufwerke auf. Konsequenterweise ist beim Aufruf ein Doppelpunkt obligatorisch: »get-childitem Alias:« listet genau wie »get-alias« alle definierten Aliase auf. Listing 2 setzt auf eindrucksvolle Weise Navigationsbefehle auf die Windows-Registry an, sehr ähnlich dem Zugriff auf ein Dateisystem.
|
Listing 2: |
|---|
01 ############################################
02 # Powershell-Skript #
03 # Legt eine Schlüsselhierarchie in der #
04 # Registry an. #
05 # (C) Dr. Holger Schwichtenberg #
06 ############################################
07 # === Unterroutine, die eine Addition ausführt
08 function Addition
09 {
10 return $args[0] + $args[1]
11 }
12
13 # === Unterroutine, die einen Schlüssel in der Registry anlegt
14 function CreateEntry
15 {
16 "Eintrag anlegen..."
17 new-Item -Name ("Eintrag #{0}" -f $args[0]) -value $args[1] -type String
18 }
19
20 ############################################
21 # === Hauptroutine
22 "PowerShell-Registry-Skript (C) Dr. Holger Schwichtenberg 2006"
23
24 # Navigation in die Registry
25 cd hklm:software
26
27 # Prüfe, ob Eintrag softwareIT-Visions vorhanden
28 $b = Get-Item IT-Visions
29 if ($b.childName -eq "IT-Visions")
30 { # Lösche vorhandenen Eintrag mit allen Unterschlüsseln
31 "Schluessel existiert bereits, loesche..."
32 cd hklm:software
33 del IT-Visions -force -recurse
34 }
35 # Erzeuge neuen Eintrag "IT-Visions"
36 "Erzeuge IT-Visions..."
37 md IT-Visions
38 cd IT-Visions
39
40 # Lege Unterschlüssel an
41 for($a=1;$a -lt 5;$a++)
42 {
43 $ergebnis = Addition $a $a
44 CreateEntry $a $ergebnis
45 }
|
Fazit und Ausblick
Microsoft erweitert das Pipeline-Konzept der Unix-Shells um die objektorientierten Konzepte des Dotnet-Framework. Admins können mit der Powershell Skripte schreiben, die in dieser Hinsicht robuster sind als übliche Unix-Skripte, weil sie sich nicht auf die Form der Ausgabe von Befehlen verlassen müssen. In der unmittelbar bevorstehenden Version der Powershell ist die Anzahl der mitgelieferten Commandlets noch gering – kein Vergleich zur Bash plus GNU-Tools.
Doch schon jetzt entwickelt sich im Internet eine rege Open-Source-Community, die damit beginnt, diese Löcher zu stopfen [7]. In der Version 2.0 will Microsoft die Shell bereits so in das Betriebssystem integrieren, dass alle Aktionen der Microsoft Management Console (MMC) als Powershell-Skripte auslegbar sein werden. (jk)
|
Infos |
|---|
|
[1] Powershell RC2, Informationen und Download: [http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx] [2] Powershell-IDE: [http://powershell.com] [3] Primalscript for Powershell: [http://www.sapien.com] [4] Informationen über das Dotnet-Framework: [http://de.wikipedia.org/wiki/.NET] [5] LDAP-Erweiterungen für die Powershell: [http://www.IT-Visions.de/c4482.aspx] [6] WBEM-Standard der Desktop Management Task Force: [http://www.dmtf.org/standards/wbem/] [7] Powershell-Community: [http://www.windows-scripting.com/PowerShell] |
|
Der Autor |
|---|
|
Dr. Holger Schwichtenberg ist als Experte für Programmierung und automatisierte Systemadministration auf der Windows-Plattform bekannt. Mit seiner Firma [www.IT-Visions.de] unterstützt er Unternehmen durch Schulung und Beratung. Er hat bei Addison-Wesley mehrere Bücher über seine Fachgebiete geschrieben. |






